package com.ysstech.common.util.fileutil;

import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.ysstech.common.entity.SheetDTO;
import com.ysstech.common.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

@Slf4j
public class FileWriterUtil {


    /**
     * 导出多个 Sheet 页
     *
     * @param response
     * @param sheetList 页数据
     * @param fileName  文件名
     */
    public static void exportExcel(HttpServletResponse response, List<SheetDTO> sheetList, String fileName, String suffix) throws Exception {
        ExcelWriter bigWriter = ExcelUtil.getBigWriter();
        // 重命名第一个Sheet的名称，不然会默认多出一个Sheet1的页
        bigWriter.renameSheet(0, sheetList.get(0).getSheetName());
        for (SheetDTO sheet : sheetList) {
            // 指定要写出的 Sheet 页
            bigWriter.setSheet(sheet.getSheetName());
            //Integer[] columnWidth = sheet.getColumnWidth();
            List<Integer> columnWidth = sheet.getColumnWidth();
            if (columnWidth == null || columnWidth.size() != sheet.getFieldAndAlias().size()) {
                // 设置默认宽度
                for (int i = 0; i < sheet.getFieldAndAlias().size(); i++) {
                    bigWriter.setColumnWidth(i, 25);
                }
            } else {
                // 设置自定义宽度
                for (int i = 0; i < columnWidth.size(); i++) {
                    bigWriter.setColumnWidth(i, columnWidth.get(i));
                }
            }
            // 设置字段和别名
            bigWriter.setHeaderAlias(sheet.getFieldAndAlias());
            // 设置只导出有别名的字段
            bigWriter.setOnlyAlias(true);
            // 设置默认行高
            //bigWriter.setDefaultRowHeight(18);
            // 设置冻结行
            //  bigWriter.setFreezePane(1);
            // 一次性写出内容，使用默认样式，强制输出标题
            bigWriter.write(sheet.getCollection(), true);
            // 设置所有列为自动宽度，不考虑合并单元格
            //bigWriter.autoSizeColumnAll();
        }
        ServletOutputStream out = null;
        try {
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" +
                            URLEncoder.encode(fileName  + "." + suffix, "UTF-8"));
            out = response.getOutputStream();
            bigWriter.flush(out, true);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭writer，释放内存
            bigWriter.close();
        }
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }



    /**
     * 导出文件
     *
     * @param title    标题
     * @param fileName 文件名
     * @param list     文件内容， map的key代表表格的列说明，value代表值
     * @param suffix   文件后缀
     */
    public static void excelExport(String title, String fileName, List<Map<String, Object>> list, String suffix,
                                   HttpServletResponse response) throws Exception {
        ExcelWriter writer = null;
        if (list != null && list.size() > 0) {
            try {
                ArrayList<Map<String, Object>> rows = CollUtil.newArrayList(list);
                // 通过工具类创建writer
                //直接下载到桌面
                //  FileSystemView fsv = FileSystemView.getFileSystemView();
                //  File com = fsv.getHomeDirectory();    //这便是读取桌面路径的方法了
                // writer = ExcelUtil.getWriter(com.getPath() + "\\" + fileName + "." + suffix);
                // 合并单元格后的标题行，使用默认标题样式
                //  writer.merge(list.get(0).size() - 1, title);
                // 一次性写出内容，使用默认样式
                //  writer.write(rows);
                // 定义单元格背景色
                //StyleSet style = writer.getStyleSet();
                // 第二个参数表示是否也设置头部单元格背景
                // style.setBackgroundColor(IndexedColors.RED, false);
                //out为OutputStream，需要写出到的目标流
                //下载提示
                writer = ExcelUtil.getWriter();
                // 合并单元格后的标题行，使用默认标题样式
                if(StringUtils.isNotBlank(title)){
                    writer.merge(list.get(0).size() - 1, title);
                }
                if(rows != null && rows.size()>0){
                    writer.write(rows);
                    response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName+"."+suffix, "UTF-8"));
                    ServletOutputStream out=response.getOutputStream();
                    writer.flush(out);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 关闭writer，释放内存
                writer.close();
            }
        }
    }


    /**
     * 根据路径下载文档
     *
     * @param response 响应
     * @param filePath 文档路径
     */
    public static void downloadFile(HttpServletResponse response, String filePath) throws Exception {
        fileOutOperation(response, filePath, "attachment");
    }

    /**
     * String类型的数据导出到文件
     *
     * @param response 响应
     * @param fileName 文件名
     * @param buffer   内容
     * @param suffix   文件后缀
     */
    public static void downloadFileBuffer(HttpServletResponse response, String buffer, String fileName, String suffix) throws Exception {
        if (StringUtils.isBlank(buffer)) {
            return;
        }
        response.setContentType("text/plain");// 一下两行关键的设置
        response.addHeader("Content-Disposition",
                "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8") + "." + suffix);
        // filename指定默认的名字
        BufferedOutputStream buff = null;
        ServletOutputStream outSTr = null;
        try {
            outSTr = response.getOutputStream();// 建立
            buff = new BufferedOutputStream(outSTr);
            buff.write(buffer.toString().getBytes("UTF-8"));
            buff.flush();
            buff.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                buff.close();
                outSTr.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据响应头部标识操作文档
     *
     * @param response 响应
     * @param filePath 文档路径
     * @param header   响应头部标识 eg: attachment, inline等
     */
    public static void fileOutOperation(HttpServletResponse response, String filePath, String header) throws Exception {
        // response.reset();
        FileInputStream fileInputStream = null;
        OutputStream outputStream = null;
        File file = null;
        try {
            file = new File(filePath);
            response.setContentType("text/plain;charset=UTF-8");
            // 下载attachment,下载时文件名必须带有后缀名,不然下载后的文件不正确,例如：合同.pdf,头像.png
            response.setHeader("content-disposition", header + "; filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
            fileInputStream = new FileInputStream(file);
            outputStream = response.getOutputStream();
            IOUtils.write(IOUtils.toByteArray(fileInputStream), outputStream);
            outputStream.flush();
        } catch (IOException e) {
            String msg = "操作文件失败";
            log.error(msg, e);
            throw new Exception(msg);
        } finally {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
            if (null != file) {
                FileUtil.delteTempFile(file);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Map<String, Object> row1 = new LinkedHashMap<>();
        row1.put("姓名", "张三");
        row1.put("年龄", 23);
        row1.put("成绩", 88.32);
        row1.put("是否合格", true);

        Map<String, Object> row2 = new LinkedHashMap<>();
        row2.put("姓名", "李四");
        row2.put("年龄", 33);
        row2.put("成绩", 59.50);
        row2.put("是否合格", false);

        List list = new ArrayList();
        list.add(row1);
        list.add(row2);
        // excelExport("11111","测试", list,"xls");

    }
}
